#ifndef __AUTOMATAS
#define __AUTOMATAS

#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <iostream>

using namespace std;

struct tNodo
{
	char simbol; 
	int state;
};

//---------------------------------------------------------------

class FiniteStateMachine
{
protected:
	set<char> _alphabet;
public:
	vector<int> finalStates;
	vector<vector<tNodo> > states;
	
	const set<char>& alphabet() { return _alphabet;}
	
	virtual void addTransition(int state1, int state2, char symbol);
	virtual void addAsFinalState(int state);
	int addState();	
	bool recognize(string word);
};

//-----------------------------------------------------------

class DeterministicFiniteAutomaton : public FiniteStateMachine
{

public:
	DeterministicFiniteAutomaton(int amountOfStates);	
	virtual int transition (int state, char symbol);	
	virtual bool recognize(string word);
	virtual bool isFinal(int state);
};

//--------------------------------------------------------------

class NondeterministicFiniteAutomaton : public FiniteStateMachine
{
protected:
	vector<vector<int> > lambdaTransitions;
	void copyStartingOn(int offset, NondeterministicFiniteAutomaton* automata);

public:
	NondeterministicFiniteAutomaton(int amountOfStates);
	virtual int getSize();
	virtual vector<int> transition(int state, char symbol);
	virtual vector<int> lambda(int state);	
	virtual bool recognize(string word);
	virtual bool isFinal(int state);
	virtual void addLambdaTransition(int state1, int state2);
	virtual void print();
	NondeterministicFiniteAutomaton* o(NondeterministicFiniteAutomaton* automata);
	NondeterministicFiniteAutomaton* concat(NondeterministicFiniteAutomaton* automata);
	NondeterministicFiniteAutomaton* kleeneClosure();
	NondeterministicFiniteAutomaton* positiveClosure();
	NondeterministicFiniteAutomaton* withOptionalOperand();
	static NondeterministicFiniteAutomaton* acceptingChar(char aCharacter);
	static NondeterministicFiniteAutomaton* acceptingDot();

	virtual vector<bool> lambda_closure(vector<bool> state);
	virtual vector<bool> transition(vector<bool> state, char symbol);

private:
	bool isFinal(vector<bool> state);
};


#endif
